`timescale 1ns / 1ps

module fc_1_top(
    input  wire         clk,
    input  wire         rst_n_fc,
    input  wire         start,
    output wire [31:0]  fc_output_data_monitor,
    output wire         fc_output_wren_monitor,
    output wire         done_o
    );
    
    wire [1:0]  input_data_addr;
    wire [1023:0] input_data;

    wire [9:0]   weight_addr;
    wire [1023:0] weight;

    wire [6:0]   bias_addr; 
    wire [7:0]   bias;

    wire          fc_output_wren;
    wire  [31:0]  fc_output_data;
    wire  [6:0]   fc_output_addr;

    wire [1023:0] mul_data1;
    wire [1023:0] mul_data2;
    wire [2047:0] mul_result;

    

    fc_input_ram u_fc_input_ram(
        .addra(input_data_addr),
        .clka(clk),
        .douta(input_data)
    );

    fc1_weight_ram u_fc_weight(
        .addra(weight_addr),
        .clka(clk),
        .douta(weight)
    );

    fc1_bias_ram u_fc_bias(
        .addra(bias_addr),
        .clka(clk),
        .douta(bias)
    );


    mult_array1 u_mult_array(
        .clk(clk),
        .rst_n(rst_n_fc),
        .data1(mul_data1),
        .data2(mul_data2),
        .result(mul_result)
    );

    assign fc_output_data_monitor = fc_output_data;
    assign fc_output_wren_monitor = fc_output_wren;



    // 每32个输出通道写入一个RAM地址
    reg [0:1023] write_buffer[0:3];
    reg [4:0] write_count;
    reg [1:0] write_addr;
    reg write_en;
    reg write_done;

    // 初始化 write_buffer，避免未定义值
    integer i;
    initial begin
        for (i = 0; i < 4; i = i + 1) begin
            write_buffer[i] = 0;
        end
    end

    always @(posedge clk or negedge rst_n_fc) begin
        if (!rst_n_fc) begin
            write_count <= 0;
            write_addr <= 0;
            write_done <= 0;
        end
        else if (fc_output_wren) begin
            write_buffer[write_addr][write_count*32 +: 32] <= fc_output_data;
            if (write_count == 31) begin
                write_count <= 0;
                if (write_addr == 3) begin
                    write_done <= 1;
                end else begin
                    write_addr <= write_addr + 1;
                end
            end
            else begin
                write_count <= write_count + 1;
            end
        end
    end

    always @(posedge clk or negedge rst_n_fc) begin
        if (!rst_n_fc) begin
            write_en <= 0;
        end
        else begin
            if (!write_done && fc_output_wren) begin
                write_en <= 1;
            end else begin
                write_en <= 0;
            end
        end
    end

    wire [6:0] dummy_addr;
    wire [31:0] dummy_data;

    buffer1 u_buffer(
        .clka(clk),
        .ena(write_en),
        .wea(1'b1),
        .addra(write_addr),
        .dina(write_buffer[write_addr]),

        .clkb(clk),
        .enb(1'b0),
        .addrb(dummy_addr),
        .doutb(dummy_data)
    );




    fc_1 u_fc(
        .clk_i(clk),
        .rst_n_i(rst_n_fc),
        .start_i(start),
        .done_o(done_o),

        .input_data_addr_o(input_data_addr),
        .input_data_i(input_data),

        .weight_addr_o(weight_addr),
        .weight_i(weight),

        .bias_addr_o(bias_addr), 
        .bias_i(bias),

        .fc_output_wren_o(fc_output_wren),
        .fc_output_data_o(fc_output_data),
        .fc_output_addr_o(fc_output_addr),

        .mul_data1_o(mul_data1),
        .mul_data2_o(mul_data2),
        .mul_result_i(mul_result)
    );

endmodule
